#include <list>
#include <map>
#include "State.h"

using namespace std;

State::State():
	bAcceptState(false)
{
	labels = new list<string>();
}

State::State(string label, bool IsAccept):
	bAcceptState(IsAccept)
{
	labels = new list<string>();
	labels->push_front(label);
}

State::State(list<string>* labelList, bool IsAccept):
	labels(labelList),
	bAcceptState(IsAccept)
{
}

State::~State()
{
	while(!labels->empty())
		labels->pop_front();
	delete labels;
}

bool State::hasLabel(string label)
{
	for(list<string>::iterator iter = labels->begin(), end = labels->end(); iter != end; ++iter)
	{
		if((*iter).compare(label) == 0)
		{
			return true;
		}
	}
	return false;
}

bool State::isAcceptState()
{
	return bAcceptState;
}

void State::makeAcceptState()
{
	bAcceptState = true;
}

void State::addLabel(string newLabel)
{
	list<string>::iterator iter = labels->begin(),
		end = labels->end();
	while(iter != end && (*iter).compare(newLabel) < 0)	//while newLabel comes after *iter
	{
		++iter;
	}
	if(iter != end)
	{
		if ((*iter).compare(newLabel) != 0)	//Therefore, the insterting label is not yet in this list
			labels->insert(iter, newLabel);
	}
	else
	{
		labels->push_back(newLabel);
	}
}

bool State::matches(State* other)
{
	list<string>::iterator thisIter = labels->begin(),
						   otherIter = other->labels->begin(),
						   thisEnd = labels->end(),
						   otherEnd = other->labels->end();
	while(thisIter != thisEnd && otherIter != otherEnd)
	{
		if((*thisIter).compare(*otherIter) != 0)
			return false;
		thisIter++; otherIter++;
	}
	if(thisIter != thisEnd || otherIter != otherEnd) return false;
	return true;
}

int State::compareTo(State* other)
{
	string thisStr = labels->front(),
		   otherStr = other->labels->front();
	return thisStr.compare(otherStr);
}

void State::combineWithState(State* other)
{
	bAcceptState = bAcceptState || other->bAcceptState;
	list<string> *newLabels = new list<string>();
	list<string>::iterator thisIter = labels->begin(),
						   otherIter = other->labels->begin(),
						   thisEnd = labels->end(),
						   otherEnd = other->labels->end();
	while(thisIter != thisEnd && otherIter != otherEnd)
	{
		if((*thisIter).compare(*otherIter) < 0)	//if *otherIter comes after *thisIter
		{
			newLabels->push_back(*thisIter);
			thisIter++;
		}
		else if((*thisIter).compare(*otherIter) > 0)	//*otherIter comes before *thisIter
		{
			newLabels->push_back(*otherIter);
			otherIter++;
		}
		else	//Identical labels, make sure we don't duplicate
		{
			newLabels->push_back(*otherIter);
			otherIter++;
			thisIter++;
		}
	}
	if(thisIter == thisEnd)
	{	//Finish off with everything that's left
		while(otherIter != otherEnd)
		{
			newLabels->push_back(*otherIter);
			otherIter++;
		}
	}
	else
	{
		while(thisIter != thisEnd)
		{
			newLabels->push_back(*thisIter);
			thisIter++;
		}
	}
	list<string>* temp = labels;
	labels = newLabels;	//replace the old with the new, delete the old.
	delete temp;
}

string State::listLabels()
{
	if(labels->size() == 0) return "EM";
	string toReturn = "{";
	for(list<string>::iterator iter = labels->begin(), end = labels->end(); iter != end; iter = iter)
	{
		toReturn += *iter++;
		if (iter != end )
		{
			toReturn += ", ";
		}
	}
	toReturn += "}";
	return toReturn;
}

InputState::InputState(State* s, char i):
	state(s),
	input(i)
{
}

InputState::~InputState()
{
	state = 0;
	input = 0;
}